/********************************************************************************/
/* Projekt  Inverter3                                                             */
/* Autor:   Gerhard Woelfl                                                      */
/* Datum:   29.05.2014                                                          */
/* Changes: 29.05.2014: Initial Version                                         */
/*                                                                              */
/********************************************************************************/

#include <xc.h>
#include "system_const.h"
#include "adc.h"
#include "timer.h"


uint8_t adcMixAnNum[NUM_OF_AN] = {V_PAS_AN_CHAN,V_DC_AN_CHAN,V_GAS_AN_CHAN,V_TEMP_AN_CHAN};
int16_t    adcMixOfs[NUM_OF_AN] = {V_PAS_OFS,V_DC_OFS,V_GAS_OFS,V_TEMP_OFS};
int16_t    adcCurOfs[3];

int16_t    adcMixGain[NUM_OF_AN] = {V_PAS_GAIN,V_DC_GAIN,V_GAS_GAIN,V_TEMP_GAIN};

int16_t    adcMixRes[NUM_OF_AN];

int16_t iu, iv, idc, vpas, vdc, vgas, vtemp;
int16_t iuFil, ivFil, idcFil, vpasFil, vdcFil, vgasFil, vtempFil;
int32_t iuFilAccu, ivFilAccu, idcFilAccu, vpasFilAccu, vdcFilAccu, vgasFilAccu, vtempFilAccu;

uint8_t mixBufIdx = 0;
// uint16_t sin_phi, cos_phi;


// ****************************************************************************
//
//	Function: void ADCInit(void)
//
// ****************************************************************************
void ADCInit()
{
    AD1CON1bits.ADSIDL = 0;     // Continues module operation in Idle mode
    AD1CON1bits.AD12B = 0;      // 10-bit, 4-channel ADC operation
    AD1CON1bits.FORM = 0x00;    // Integer (DOUT = 0000 00dd dddd dddd)
    AD1CON1bits.SSRC = 0b000;   // PWM Generator 1 primary trigger compare ends sampling and starts conversion
    AD1CON1bits.SSRCG = 1;      // Sample Trigger Source Group bit
    AD1CON1bits.SIMSAM = 1;     // Samples CH0, CH1, CH2, CH3 simultaneously
    AD1CON1bits.ASAM = 0;       // Sampling begins when the SAMP bit is set

    AD1CON2bits.VCFG = 0b000;   // VREFH = AVDD, VREFL = AVSS
    AD1CON2bits.CSCNA = 0;      // Does not scan inputs
    AD1CON2bits.CHPS = 0b10;    // Converts CH0, CH1, CH2 and CH3
    AD1CON2bits.SMPI = 0b00000; // Generates interrupt after completion of every sample/conversion operation
    AD1CON2bits.BUFM = 0;       // Always starts filling the buffer from the start address
    AD1CON2bits.ALTS = 0;       // Always uses channel input selects for Sample MUXA

    AD1CON3bits.ADRC = 0;       // Clock derived from system clock
    AD1CON3bits.SAMC = 0b1111; // Auto-Sample Time bits
    AD1CON3bits.ADCS = 255;     // (n + 1) * Tp = Tad

    AD1CON4bits.ADDMAEN = 0;    // Conversion results are stored in ADC1BUF0 through ADC1BUFF registers; DMA will not be used

    AD1CHS123bits.CH123NA = 0x00;   // Neg. Input for CH1 / CH2 / CH3 = VREFL
    AD1CHS123bits.CH123SA = 0;      // Pos. Input for CH1 = AN0
                                    //                CH2 = AN1
                                    //                CH3 = AN2

    AD1CHS0bits.CH0NA = 0;      // CH0 negative input is VREFL
    AD1CHS0bits.CH0SA = adcMixAnNum[0];      // CH0 positive input

    // Settings for first SW triggered convertion
    // AD1CON1bits.SSRC = 0b000;   // Clearing the Sample bit (SAMP) ends sampling and starts conversion (Manual mode)
    AD1CON1bits.SSRC = 0b111;   // Internal counter ends sampling and starts conversion (auto-convert)
    AD1CON1bits.SSRCG = 0;      // Sample Trigger Source Group bit
    AD1CON1bits.ASAM = 0;       // Sampling begins when SAMP is set

    // AD1CON3bits.ADCS = 0b11111111; // ADC1 Conversion Clock Select bits = TP * 256 = TAD
    AD1CON3bits.ADCS = 0b00000111; // ADC1 Conversion Clock Select bits = TP * 256 = TAD

    IPC3bits.AD1IP = 0b110;      // Set AD1 Interrupt Priority Level
    IFS0bits.AD1IF = 0;          // Clear AD1 Interrupt Flag
    IEC0bits.AD1IE = 1;          // Enable AD1 interrupt

    AD1CON1bits.ADON = 1;       // ADC module is operating

    return;

}

// ****************************************************************************
//
//	Function: void getAdcOfs(void)
//
// ****************************************************************************
void getAdcOfs(void)
{

    // begin sampling (SW triggered)
    // AD1CON1bits.SIMSAM = 0;     // Samples CH0, CH1, CH2, CH3 simultaneously
    // AD1CON1bits.SAMP = 1;       // begin sampling
    // delay_4_2us(1);
    // AD1CON1bits.SAMP = 1;       // stop sampling and begin conversion

    AD1CON1bits.SAMP    = 1;
    while(!AD1CON1bits.SAMP);
    AD1CON1bits.SAMP    = 0;
    while(AD1CON1bits.SAMP);
    // LED = ~LED;
    while(!AD1CON1bits.DONE);
    //Data is available in ADC1BUF0



    // while (!(AD1CON1bits.DONE)); // wait for conversion DONE

    adcMixOfs[0] = ADC1BUF0;
    adcCurOfs[0] = ADC1BUF1;
    adcCurOfs[1] = ADC1BUF2;
    adcCurOfs[2] = ADC1BUF3;

    AD1CON1bits.SSRCG = 1;      // Sample Trigger Source Group bit
                                // Sampling is now triggered by PWM
    AD1CON1bits.SSRC = 0b000;   // PWM Generator 1 primary trigger compare ends sampling and starts conversion
    AD1CON1bits.ASAM = 1;
    AD1CON1bits.SAMP = 1;       // begin sampling

    return;

}


// ****************************************************************************
//
//	Function: void getAdcVals(void)
//
// ****************************************************************************
void getAdcVals(void)
{

    iu  = (int16_t)(__builtin_mulss((ADC1BUF1-adcCurOfs[0]),CUR_GAIN) >> (15-SHIFT_CUR));
    iv  = (int16_t)(__builtin_mulss((ADC1BUF2-adcCurOfs[1]),CUR_GAIN) >> (15-SHIFT_CUR));
    idc = (int16_t)(__builtin_mulss((ADC1BUF3-adcCurOfs[2]),CUR_GAIN) >> (15-SHIFT_CUR));

    // filter iu ****************************************
    iuFilAccu -= (iuFilAccu >> I_U_FIL_SHIFT);
    iuFilAccu += iu;
    iuFil      = (int16_t)(iuFilAccu >> I_U_FIL_SHIFT);

    // filter iv ****************************************
    ivFilAccu -= (ivFilAccu >> I_V_FIL_SHIFT);
    ivFilAccu += iv;
    ivFil      = (int16_t)(ivFilAccu >> I_V_FIL_SHIFT);

    // filter idc ****************************************
    idcFilAccu -= (idcFilAccu >> I_DC_FIL_SHIFT);
    idcFilAccu += idc;
    idcFil      = (int16_t)(idcFilAccu >> I_DC_FIL_SHIFT);

    adcMixRes[mixBufIdx] = (int16_t)(__builtin_mulss((ADC1BUF0-adcMixOfs[mixBufIdx]),adcMixGain[mixBufIdx]) >> (15-SHIFT_CUR));
    // debugDummy = (int16_t)(__builtin_mulss((ADC1BUF0-adcMixOfs[mixBufIdx]),adcMixGain[mixBufIdx]) >> (15-SHIFT_CUR));
    // adcMixRes[mixBufIdx] = debugDummy;

    // filter mixed signal ********************************
    switch (mixBufIdx)
    {
        case V_PAS_BUF_IDX:
            vpas         = adcMixRes[V_PAS_BUF_IDX];
            vpasFilAccu -= (vpasFilAccu >> V_PAS_FIL_SHIFT);
            vpasFilAccu += vpas;
            vpasFil      = (int16_t)(vpasFilAccu >> V_PAS_FIL_SHIFT);
            break;
        case V_DC_BUF_IDX:
            vdc         = adcMixRes[V_DC_BUF_IDX];
            vdcFilAccu -= (vdcFilAccu >> V_DC_FIL_SHIFT);
            vdcFilAccu += vdc;
            vdcFil      = (int16_t)(vdcFilAccu >> V_DC_FIL_SHIFT);
            break;
        case V_GAS_BUF_IDX:
            vgas         = adcMixRes[V_GAS_BUF_IDX];
            vgasFilAccu -= (vgasFilAccu >> V_GAS_FIL_SHIFT);
            vgasFilAccu += vgas;
            vgasFil      = (int16_t)(vgasFilAccu >> V_GAS_FIL_SHIFT);
            break;
        case V_TEMP_BUF_IDX:
            vtemp         = adcMixRes[V_TEMP_BUF_IDX];
            vtempFilAccu -= (vtempFilAccu >> V_TEMP_FIL_SHIFT);
            vtempFilAccu += vtemp;
            vtempFil      = (int16_t)(vtempFilAccu >> V_TEMP_FIL_SHIFT);
            break;
        default:
            break;
    }
    // setup ADC MUX for mix channels
    if (mixBufIdx < (NUM_OF_AN-1))
    {
        mixBufIdx++;
    }
    else
    {
        mixBufIdx = 0;
    }

    AD1CHS0bits.CH0SA = adcMixAnNum[mixBufIdx];


    return;

}

